Skip to main content

Effective Abstraction

Learning Objectives
  • Use type hints in Python function definitions
  • Explain the benefits of using type hints in Python
  • Use functions to abstract away complexity
  • Use return types effectively
  • Break down a single function into many smaller functions
  • Explain the difference between `print()` and `return` in Python

Pre-work​

Setup​

If nobody has done so already, copy and paste this command into slack

/prework Effective Abstraction

Read​

Read the following articles:

Answer​

  • What is the difference between a print() and a return statement?
  • What is the difference between a function definition and a function call?
  • When would you use a return statement?
  • When would you use a print() statement?
  • What are function parameters?

Watch​

Watch this video to deepen your understanding of scope

Workshop​

Setup​

Ask the trainees to define abstraction. Why might it be useful?

Explain that abstraction

  • Hides detail so we can work at the right level
  • Makes code easier to use and harder to break

Explain that in Python, functions are our main tool for abstraction

Lecture​

Explain the principles of effective functions:

  • A function should do one job
  • A function should have clear inputs (parameters) and outputs (return values)
  • Prefer return over print() for reusable logic
  • Functions should be predictable: same input, same output

Show the following messy function:

def play_game():
user = input("Enter rock, paper or scissors: ").lower()
import random
cpu = random.choice(["rock", "paper", "scissors"])
if user == cpu:
print("Draw")
elif (user == "rock" and cpu == "scissors") or \
(user == "scissors" and cpu == "paper") or \
(user == "paper" and cpu == "rock"):
print("You win!")
else:
print("Computer wins!")

Ask the trainees: What are the problems here?

  • Too much responsibility in one place
  • No return values, only prints

Explain that the goal is to break this into smaller, focused functions:

  • Pitfall: printing in logic functions → Fix: use return values
  • Pitfall: vague names → Fix: name by outcome (e.g. determine_winner)
  • Pitfall: too much code in one function → Fix: separate input, logic, and output

Live Code the following example of a simple function:

from random import choice

...

def random_move() -> str:
"""Return one of: 'rock', 'paper', 'scissors'."""
return choice(["rock", "paper", "scissors"])

Task​

Explain that we’re going to build Rock–Paper–Scissors from small functions

Suggest two starting functions, but emphasise that more will be needed for a complete game:

  • One function to handle user input
  • One function to decide who wins

Explain that the important part is breaking the problem into reusable pieces

Task the trainees (individually):

  • Build a Rock–Paper–Scissors game as a set of small functions
  • Requirements:
    • At least three functions of your own design
    • Type hints and docstrings!
    • Logic functions must use return values, don’t print inside them
    • The game should let a person play Rock–Paper–Scissors against the computer

Wrap-up​

Ask trainees if they have any questions